# Copyright (c) 2018 Presto Labs Pte. Ltd.
# Author: inkyu

import re

from pymongo import MongoClient
from datetime import datetime, timedelta
from forex_python.converter import CurrencyRates

db = MongoClient(
    'mongodb://inkyu_legacy:xArT3T#dXtGfSBDV@13.251.33.84:42006/coin_20181121').pnl_20181201
c = CurrencyRates()

today = datetime.now()
until_dt = datetime(year=today.year, month=today.month, day=today.day, hour=0)
from_dt = until_dt - timedelta(days=1)

dead_strategies = [
    {
        'db': 'bithumb_huobi',
        'full_name': 'Bithumb => Huobi PassAgg',
        'type': 'pass-agg-kr',
    },
    {
        'db': 'bitfinex', 'full_name': 'Bitfinex (<= Binance) Unhedge', 'type': 'usdt'
    },
    {
        'db': 'bitfinex_huobi',
        'full_name': 'Bitfinex => Huobi PassAgg',
        'type': 'pass-agg-hk',
    },
    {
        'db': 'hitbtc_a',
        'full_name': 'HitBtc (<= Binance) Unhedge',
        'type': 'usdt',
    },
    {
        'db': 'hitbtc_b',
        'full_name': 'HitBtc (<= Binance) Unhedge',
        'type': 'usdt',
    },
    {
        'db': 'huobi_a',
        'full_name': 'Huobi (<= Binance) Unhedge',
        'type': 'usdt',
    },
    {
        'db': 'huobi_b',
        'full_name': 'Huobi (<= Binance) Unhedge',
        'type': 'usdt',
    },
    {
        'db': 'bithumb_neo2',
        'full_name': 'Bithumb (<= Binance) Unhedge',
        'type': 'krw',
    },
    {
        'db': 'kraken',
        'old_server': 'u05',
        'full_name': 'Kraken (<= Binance) Unhedge (EUR)',
        'type': 'eur',
    },
    {
        'db': 'kraken_usd',
        'old_server': 'u02',
        'full_name': 'Kraken (<= Binance) Unhedge (USD)',
        'type': 'usd',
    },
    {
        'db': 'okex_upbit',
        'full_name': 'Okex => Upbit PassAgg',
        'type': 'pass-agg',
    },
    {
        'db': 'kraken_okex_usd',
        'server': 'u02',
        'full_name': 'Kraken => Okex PassAgg',
        'type': 'pass-agg-usd',
    },
    {
        'db': 'okex_bithumb',  #'server': 'k06',
        'full_name': 'Okex => Bithumb PassAgg',
        'type': 'pass-agg',
    },
    {
        'db': 'bitfinex_okex',  #'server': 'a17',
        'full_name': 'Bitfinex => Okex PassAgg',
        'type': 'pass-agg-hk',
    },
]

live_strategies = [
    {
        'db': 'hitbtc_binance',
        'server': 'h05',
        'full_name': 'Hitbtc => Binance PassAgg',
        'type': 'pass-agg-hk',
    },
    {
        'db': 'upbit_okex',
        'server': 'k01',
        'full_name': 'Upbit => Okex PassAgg',
        'type': 'pass-agg-kr',
    },
    {
        'db': 'huobi_upbit',
        'server': 'h04',
        'full_name': 'Huobi => Upbit PassAgg',
        'type': 'pass-agg',
    },
    {
        'db': 'bitfinex_upbit',
        'server': 'u01',
        'full_name': 'Bitfinex => Upbit PassAgg',
        'type': 'pass-agg',
    },
    {
        'db': 'bitfinex_bithumb',
        'server': 'k06',
        'full_name': 'Bitfinex => Bithumb PassAgg',
        'type': 'pass-agg',
    },
    {
        'db': 'okex_huobi',
        'server': 'h04',
        'full_name': 'Okex => Huobi PassAgg',
        'type': 'pass-agg-hk',
    },
    {
        'db': 'huobi_okex',
        'server': 'h03',
        'full_name': 'Huobi => Okex PassAgg',
        'type': 'pass-agg-hk',
    },
    {
        'db': 'hitbtc_okex',
        'server': 'a17',
        'full_name': 'Hitbtc => Okex PassAgg',
        'type': 'pass-agg-hk',
    },
    {
        'db': 'bithumb_okex',
        'server': 'k01',
        'full_name': 'Bithumb => Okex PassAgg',
        'type': 'pass-agg-kr',
    },
    {
        'db': 'huobi_bithumb',
        'server': 'k01',
        'full_name': 'Huobi => Bithumb PassAgg',
        'type': 'pass-agg',
    },
    {
        'db': 'upbit_a',
        'server': 'k02a',
        'full_name': 'Upbit (<= Binance) Unhedge',
        'type': 'krw',
    },
    {
        'db': 'upbit_b',
        'server': 'k02b',
        'full_name': 'Upbit (<= Binance) Unhedge',
        'type': 'krw',
    },
    {
        'db': 'bithumb_a',
        'server': 'k08',
        'full_name': 'Bithumb Unhedge',
        'type': 'krw',
    },
    {
        'db': 'bithumb_b',
        'server': 'k04',
        'full_name': 'Bithumb Unhedge',
        'type': 'krw',
    },
    {
        'db': 'kraken_okex_eur',
        'server': 'u05',
        'full_name': 'Kraken => Okex PassAgg',
        'type': 'pass-agg-eur',
    },
]


def find_match(name, mode='all'):
  if mode == 'dead':
    strategies_list = dead_strategies
  elif mode == 'live':
    strategies_list = live_strategies
  elif mode == 'all':
    dead_one = find_match(name, 'dead')
    live_one = find_match(name, 'live')
    if dead_one is None and live_one is None:
      return None
    assert bool(dead_one) != bool(live_one), (name, dead_one, live_one)
    if dead_one:
      return dead_one
    else:
      return live_one
  else:
    raise ValueError('invalid mode %s!' % mode)

  find_list = []
  for info in strategies_list:
    pattern = '^' + info['db'] + '([_]?[0-9]+)?$'
    if re.match(pattern, name):
      find_list.append(info)

  if find_list:
    assert len(find_list) == 1, find_list
    return find_list[0].copy()
  else:
    return None


def gen_full_strategy_list():
  dead_strat_list = []
  live_strat_list = []

  collection_names = db.list_collection_names()
  for name in sorted(collection_names):
    record = find_match(name)
    if record is None:
      print('Unknown collection name: ', name)
      continue

    if name[-1].isdigit():
      record.pop('server', None)

    record['db'] = name

    if 'server' in record:
      live_strat_list.append(record)
    else:
      dead_strat_list.append(record)
  return dead_strat_list + live_strat_list


strategies = gen_full_strategy_list()
pnl = 0.
pnl_prime = 0.
value = 0.
value_prime = 0.

for strategy in strategies:
  query = db[strategy['db']].find({'timestamp': {'$gt': from_dt, '$lt': until_dt}})
  try:
    first = query.sort([('timestamp', 1)]).limit(1)[0]
    last = query.sort([('timestamp', -1)]).limit(1)[0]
  except IndexError:
    continue
  print("```")
  days = (last['timestamp'] - first['timestamp']).days
  days_str = ''
  if days > 0:
    days_str = '%dD ' % days
  print('* %s %s: %s(%s%.2fH)' %
        (strategy.get('server', 'DEPRECATED'),
         strategy['full_name'],
         last['timestamp'].strftime('%Y-%m-%d %H:%M:%S'),
         days_str, (last['timestamp'] - first['timestamp']).seconds / 3600))
  ema = last['ema_price']
  days += (last['timestamp'] - first['timestamp']).seconds / 24 / 3600
  active = 'server' in strategy

  if strategy['type'] == 'pass-agg-hk':
    krw = last['usdt_pass'] + last['usdt_pass_pos']
    usdt = last['usdt_agg'] + last['usdt_agg_pos']
    if 'usdt_pass_reserve' in last:
      print('Total USDT(Pass): %.2f (quote: %.2f + base: %.2f) / %.2f (%.2f%%)' %
            (last['usdt_agg_bal'] + last['usdt_agg'],
             last['usdt_agg'],
             last['usdt_agg_bal'],
             last['usdt_agg_reserve'],
             100. * (last['usdt_agg_bal'] + last['usdt_agg']) / last['usdt_agg_reserve']))
      print('Total USDT(Agg): %.2f (quote: %.2f + base: %.2f) / %.2f (%.2f%%)' %
            (last['usdt_pass_bal'] + last['usdt_pass'],
             last['usdt_pass'],
             last['usdt_pass_bal'],
             last['usdt_pass_reserve'],
             100. * (last['usdt_pass_bal'] + last['usdt_pass']) / last['usdt_pass_reserve']))
    print('Last USDT(Pass): %f (quote: %f + position: %f) ' %
          (usdt, last['usdt_agg'], last['usdt_agg_pos']))
    print('Last USDT(Agg): %f (quote: %f + position: %f) ' %
          (krw, last['usdt_pass'], last['usdt_pass_pos']))
    krw_diff = krw - (first['usdt_pass'] + first['usdt_pass_pos'])
    usdt_diff = usdt - (first['usdt_agg'] + first['usdt_agg_pos'])
    print('ΔUSDT(Pass): %f' % usdt_diff)
    rate = c.get_rate('USD', 'USD', until_dt)
    print('ΔUSDT(Agg) : %f ~= %f USDT (%f USDT/USDT)' % (krw_diff, krw_diff / rate, rate))
    print('ΔUSDT(Agg)\': %f ~= %f USDT (%f USDT/USDT)' %
          (krw_diff, krw_diff / last['ema_price'], last['ema_price']))
    print(' PnL : %f' % (usdt_diff + krw_diff / rate))
    efficiency = ''
    if 'usdt_pass_reserve' in last:
      efficiency = '(%.2fbp / day)' % (1e4 * (usdt_diff + krw_diff / last['ema_price'])
                                       / last['usdt_pass_reserve'] / 2 / days)
    print(' PnL\': %f %s' % (usdt_diff + krw_diff / last['ema_price'], efficiency))
    pnl += usdt_diff + krw_diff / rate
    pnl_prime += usdt_diff + krw_diff / last['ema_price']
    if active:
      value += last['usdt_agg_bal'] + last['usdt_agg'] + (last['usdt_pass_bal']
                                                          + last['usdt_pass']) / rate
      value_prime += last['usdt_agg_bal'] + last['usdt_agg'] + (
          last['usdt_pass_bal'] + last['usdt_pass']) / last['ema_price']
  elif strategy['type'] in ('pass-agg', 'pass-agg-kr'):
    if strategy['type'] == 'pass-agg-kr':
      prime_rate = 1. / last['ema_price']
    else:
      prime_rate = last['ema_price']

    if 'krw_reserve' in last:
      print('Total KRW: %.2f (quote: %.2f + base: %.2f) / %.2f (%.2f%%)' %
            (last['krw_bal'] + last['krw'],
             last['krw'],
             last['krw_bal'],
             last['krw_reserve'],
             100. * (last['krw_bal'] + last['krw']) / last['krw_reserve']))
      print('Total USDT: %.2f (quote: %.2f + base: %.2f) / %.2f (%.2f%%)' %
            (last['usdt_bal'] + last['usdt'],
             last['usdt'],
             last['usdt_bal'],
             last['usdt_reserve'],
             100. * (last['usdt_bal'] + last['usdt']) / last['usdt_reserve']))
    krw = last['krw'] + last['krw_pos']
    usdt = last['usdt'] + last['usdt_pos']
    print('KRW: %f (quote: %f + position: %f) ' % (krw, last['krw'], last['krw_pos']))
    print('Last USDT: %f (quote: %f + position: %f) ' % (usdt, last['usdt'], last['usdt_pos']))
    krw_diff = krw - (first['krw'] + first['krw_pos'])
    usdt_diff = usdt - (first['usdt'] + first['usdt_pos'])
    print('ΔUSDT: %f' % usdt_diff)
    rate = c.get_rate('USD', 'KRW', until_dt)
    print('ΔKRW : %f ~= %f USDT (%f KRW/USDT)' % (krw_diff, krw_diff / rate, rate))
    print('ΔKRW\': %f ~= %f USDT (%f KRW/USDT)' % (krw_diff, krw_diff / prime_rate, prime_rate))
    print(' PnL : %f' % (usdt_diff + krw_diff / rate))
    efficiency = ''
    value_prime_cur = 0.
    value_cur = 0.
    if active:
      value_cur = last['usdt_bal'] + last['usdt'] + (last['krw_bal'] + last['krw']) / rate
      value += value_cur
      value_prime_cur = last['usdt_bal'] + last['usdt'] + (last['krw_bal']
                                                           + last['krw']) / prime_rate
      value_prime += value_prime_cur
    if value_prime_cur:
      efficiency = '(%.2fbp / day)' % (1e4 *
                                       (usdt_diff + krw_diff / prime_rate) / value_prime_cur / days)
    print(' PnL\': %f %s' % (usdt_diff + krw_diff / prime_rate, efficiency))
    pnl += usdt_diff + krw_diff / rate
    pnl_prime += usdt_diff + krw_diff / prime_rate
  elif strategy['type'] == 'pass-agg-eur':
    prime_rate = 1 / last['ema_price']
    if 'eur_reserve' in last:
      print('Total EUR: %.2f (quote: %.2f + base: %.2f) / %.2f (%.2f%%)' %
            (last['eur_bal'] + last['eur'],
             last['eur'],
             last['eur_bal'],
             last['eur_reserve'],
             100. * (last['eur_bal'] + last['eur']) / last['eur_reserve']))
      print('Total USDT: %.2f (quote: %.2f + base: %.2f) / %.2f (%.2f%%)' %
            (last['usdt_bal'] + last['usdt'],
             last['usdt'],
             last['usdt_bal'],
             last['usdt_reserve'],
             100. * (last['usdt_bal'] + last['usdt']) / last['usdt_reserve']))
    eur = last['eur'] + last['eur_pos']
    usdt = last['usdt'] + last['usdt_pos']
    print('EUR: %f (quote: %f + position: %f) ' % (eur, last['eur'], last['eur_pos']))
    print('Last USDT: %f (quote: %f + position: %f) ' % (usdt, last['usdt'], last['usdt_pos']))
    eur_diff = eur - (first['eur'] + first['eur_pos'])
    usdt_diff = usdt - (first['usdt'] + first['usdt_pos'])
    print('ΔUSDT: %f' % usdt_diff)
    rate = c.get_rate('USD', 'EUR', until_dt)
    print('ΔEUR : %f ~= %f USDT (%f EUR/USDT)' % (eur_diff, eur_diff / rate, rate))
    print('ΔEUR\': %f ~= %f USDT (%f EUR/USDT)' % (eur_diff, eur_diff / prime_rate, prime_rate))
    print(' PnL : %f' % (usdt_diff + eur_diff / rate))
    efficiency = ''
    value_prime_cur = 0.
    value_cur = 0.
    if active:
      value_cur = last['usdt_bal'] + last['usdt'] + (last['eur_bal'] + last['eur']) / rate
      value += value_cur
      value_prime_cur = last['usdt_bal'] + last['usdt'] + (last['eur_bal']
                                                           + last['eur']) / prime_rate
      value_prime += value_prime_cur
    if value_prime_cur:
      efficiency = '(%.2fbp / day)' % (1e4 *
                                       (usdt_diff + eur_diff / prime_rate) / value_prime_cur / days)
    print(' PnL\': %f %s' % (usdt_diff + eur_diff / prime_rate, efficiency))
    pnl += usdt_diff + eur_diff / rate
    pnl_prime += usdt_diff + eur_diff / prime_rate
  elif strategy['type'] == 'pass-agg-usd':
    prime_rate = 1 / last['ema_price']
    if 'usd_reserve' in last:
      print('Total USD: %.2f (quote: %.2f + base: %.2f) / %.2f (%.2f%%)' %
            (last['usd_bal'] + last['usd'],
             last['usd'],
             last['usd_bal'],
             last['usd_reserve'],
             100. * (last['usd_bal'] + last['usd']) / last['usd_reserve']))
      print('Total USDT: %.2f (quote: %.2f + base: %.2f) / %.2f (%.2f%%)' %
            (last['usdt_bal'] + last['usdt'],
             last['usdt'],
             last['usdt_bal'],
             last['usdt_reserve'],
             100. * (last['usdt_bal'] + last['usdt']) / last['usdt_reserve']))
    usd = last['usd'] + last['usd_pos']
    usdt = last['usdt'] + last['usdt_pos']
    print('USD: %f (quote: %f + position: %f) ' % (usd, last['usd'], last['usd_pos']))
    print('Last USDT: %f (quote: %f + position: %f) ' % (usdt, last['usdt'], last['usdt_pos']))
    usd_diff = usd - (first['usd'] + first['usd_pos'])
    usdt_diff = usdt - (first['usdt'] + first['usdt_pos'])
    print('ΔUSDT: %f' % usdt_diff)
    rate = 1.0
    print('ΔUSD : %f ~= %f USDT (%f USD/USDT)' % (usd_diff, usd_diff / rate, rate))
    print('ΔUSD\': %f ~= %f USDT (%f USD/USDT)' % (usd_diff, usd_diff / prime_rate, prime_rate))
    print(' PnL : %f' % (usdt_diff + usd_diff / rate))
    efficiency = ''
    value_prime_cur = 0.
    value_cur = 0.
    if active:
      value_cur = last['usdt_bal'] + last['usdt'] + (last['usd_bal'] + last['usd']) / rate
      value += value_cur
      value_prime_cur = last['usdt_bal'] + last['usdt'] + (last['usd_bal']
                                                           + last['usd']) / prime_rate
      value_prime += value_prime_cur
    if value_prime_cur:
      efficiency = '(%.2fbp / day)' % (1e4 *
                                       (usdt_diff + usd_diff / prime_rate) / value_prime_cur / days)
    print(' PnL\': %f %s' % (usdt_diff + usd_diff / prime_rate, efficiency))
    pnl += usdt_diff + usd_diff / rate
    pnl_prime += usdt_diff + usd_diff / prime_rate
  else:
    currency = strategy['type'].upper()
    if 'reserve' in last:
      cur = strategy['type']
      print('Total %s: %.2f (quote: %.2f + base: %.2f) / %.2f (%.2f%%)' %
            (currency,
             last['bal'] + last[cur],
             last[cur],
             last['bal'],
             last['reserve'] * 2,
             100. * (last['bal'] + last[cur]) / last['reserve'] / 2))
    quote = last[strategy['type']]
    position = last[strategy['type'] + '_pos']
    print('Last %s: %f (quote: %f + position: %f) ' % (currency, quote + position, quote, position))
    quote_diff = quote + position - (first[strategy['type']] + first[strategy['type'] + '_pos'])
    rate = c.get_rate('USD', currency[:3], until_dt)
    print('Δ%s : %f ~= %f USDT (%f %s/USDT)' %
          (currency, quote_diff, quote_diff / rate, rate, currency))
    print('Δ%s\': %f ~= %f USDT (%f %s/USDT)' %
          (currency, quote_diff, quote_diff * last['ema_price'], 1 / last['ema_price'], currency))
    print(' PnL : %f' % (quote_diff / rate))
    efficiency = ''
    if 'reserve' in last:
      efficiency = '(%.2fbp / day)' % (1e4 * quote_diff / last['reserve'] / 2 / days)
    print(' PnL\': %f %s' % (quote_diff * last['ema_price'], efficiency))
    pnl += quote_diff / rate
    pnl_prime += quote_diff * last['ema_price']
    if active:
      value += (last['bal'] + last[cur]) / rate
      value_prime += (last['bal'] + last[cur]) * last['ema_price']

  print("```")

print()
print('Total PnL : %f' % pnl)
print('Total PnL\': %f' % pnl_prime)
print('Total Value : %f' % value)
print('Total Value\': %f' % value_prime)
